package com.yixia.system.service.impl.system;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yixia.common.annotation.DataScope;
import com.yixia.common.core.domain.AjaxResult;
import com.yixia.common.core.domain.entity.SysRole;
import com.yixia.common.core.domain.entity.SysUser;
import com.yixia.common.utils.SecurityUtils;
import com.yixia.common.utils.StringUtils;
import com.yixia.system.domain.system.SysRoleDept;
import com.yixia.system.domain.system.SysRoleMenu;
import com.yixia.system.domain.system.SysUserRole;
import com.yixia.system.mapper.system.SysRoleDeptMapper;
import com.yixia.system.mapper.system.SysRoleMapper;
import com.yixia.system.mapper.system.SysRoleMenuMapper;
import com.yixia.system.mapper.system.SysUserRoleMapper;
import com.yixia.system.service.system.SysRoleService;
import com.yixia.system.service.system.SysUserRoleService;
import com.yixia.common.constant.UserConstants;
import com.yixia.common.exception.ServiceException;

import com.yixia.common.utils.page.PageBean;
import com.yixia.common.utils.spring.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
* @author 35038
* @description 针对表【sys_role】的数据库操作Service实现
* @createDate 2023-06-02 19:15:05
*/
@Slf4j
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole>
    implements SysRoleService {




    @Autowired
    private SysRoleMapper roleMapper;

    @Autowired
    private SysRoleMenuMapper roleMenuMapper;

    @Autowired
    private SysUserRoleMapper userRoleMapper;

    @Autowired
    private SysUserRoleService userRoleService;

    @Autowired
    private SysRoleDeptMapper roleDeptMapper;

    /**
     * 根据角色id来获取用户权限
     * @param userId
     */
    @Override
    public Set<String> selectRolePermissionByUserId(Long userId) {
        /*1.先根据用户获取用户对应的角色信息，查询用户角色表获取用户对应的角色*/
        List<SysRole> sysRoles = selectRolesByUserId(userId);
        /*创建权限集合*/
        Set<String> permSet = new HashSet<>();
        /*2.对这些角色进行查询，查询这些角色所拥有的权限*/
        for (SysRole sysRole : sysRoles) {
            if(StringUtils.isNotNull(sysRole) && sysRole.getRoleKey() != null){
                /*该角色不为空*/
                permSet.addAll(Arrays.asList(sysRole.getRoleKey().trim().split(",")));
            }
        }
        /*3.返回权健集合*/
        return permSet;
    }

    /**
     * 分页查询
     */
    @Override
    public AjaxResult slectRolePageList(PageBean pageBean, SysRole role) {
        /*1.对sysrole中的数据进行条件查询*/
        LambdaQueryWrapper<SysRole> queryWrapper = new LambdaQueryWrapper<SysRole>();
        queryWrapper.eq(role.getRoleId() != null, SysRole::getRoleId, role.getRoleId());
        queryWrapper.like(role.getRoleName() != null && !"".equals(role.getRoleName()), SysRole::getRoleName, role.getRoleName());
        queryWrapper.like(role.getRoleKey() != null && !"".equals(role.getRoleKey()), SysRole::getRoleKey, role.getRoleKey());
        queryWrapper.eq(role.getStatus() != null && !"".equals(role.getStatus()), SysRole::getStatus, role.getStatus());
        queryWrapper.eq(SysRole::getDelFlag, '0');
        /*进行时间的查询*/
        queryWrapper.gt(role.getBeginTime() != null, SysRole::getCreateTime, role.getBeginTime());
        queryWrapper.lt(role.getEndTime() != null,SysRole::getCreateTime, role.getEndTime());


        /*2.指定查询顺序*/
        queryWrapper.orderByAsc(SysRole::getRoleSort);/*指定查询顺序*/

        /*3.创建查询的page*/
        Page<SysRole> page = new Page<>(pageBean.getPageNum(), pageBean.getPageSize());

        /*4.进行分页查询*/
        Page<SysRole> pageResult = this.page(page, queryWrapper);

        /*5.获取集合*/
        List<SysRole> roleList = pageResult.getRecords();

        /*7.进行数据的返回*/
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("roleList", roleList);
        resultMap.put("total", pageResult.getTotal());/*总记录数*/
        return AjaxResult.success(resultMap);
    }


    /**
     * 根据用户ID查询角色
     * @param userId 用户ID
     * @return 角色列表
     */
    public List<SysRole> selectRolesByUserId(Long userId) {
        /*查询用户角色表获取所有的角色ID*/
        List<SysUserRole> sysUserRoles = userRoleMapper.selectListByUserId(userId);
        List<Long> collect = sysUserRoles.stream().map(SysUserRole::getRoleId)
                .collect(Collectors.toList());
        /*根据角色ID获取角色信息*/
        List<SysRole> userRoles = roleMapper.selectRolePermissionByUserId(collect);
        return userRoles;
    }


    /**
     * 获取全部用户并使用授权值
     * @param userId
     * @return
     */
    @Override
    public List<SysRole> selectAllRolesOnAuthRoleByUserId(Long userId){
        List<SysRole> userRoles = selectRolesByUserId(userId);
        List<SysRole> roles = selectRoleAll();
        for (SysRole role : roles)
        {
            for (SysRole userRole : userRoles)
            {
                if (role.getRoleId().longValue() == userRole.getRoleId().longValue())
                {
                    role.setFlag(true);
                    break;
                }
            }
        }
        return roles;
    }

    /**
     * 查询所有的角色信息
     * @return 角色信息
     */
    public List<SysRole> selectRoleAll() {
        return SpringUtils.getAopProxy(this).selectRoleList(new SysRole());
    }

    /**
     * 修改数据权限信息
     *
     * @param role 角色信息
     * @return 结果
     */
    @Override
    @Transactional
    public int authDataScope(SysRole role)
    {
        // 修改角色信息
        roleMapper.updateRole(role);
        // 删除角色与部门关联
        roleDeptMapper.deleteRoleDeptByRoleId(role.getRoleId());
        // 新增角色和部门信息（数据权限）
        return insertRoleDept(role);
    }

    /**
     * 新增角色部门信息(数据权限)
     *
     * @param role 角色对象
     */
    private int insertRoleDept(SysRole role) {
        int rows = 1;
        // 新增角色与部门（数据权限）管理
        List<SysRoleDept> list = new ArrayList<SysRoleDept>();
        for (Long deptId : role.getDeptIds())
        {
            SysRoleDept rd = new SysRoleDept();
            rd.setRoleId(role.getRoleId());
            rd.setDeptId(deptId);
            list.add(rd);
        }
        if (list.size() > 0)
        {
            rows = roleDeptMapper.batchRoleDept(list);
        }
        return rows;
    }


    public List<SysRole> selectRoleList(SysRole role) {
        LambdaQueryWrapper<SysRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysRole::getDelFlag, '0');
        return roleMapper.selectList(queryWrapper);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /*判断该角色名称是否存在*/
    @Override
    public boolean checkRoleNameUnique(SysRole role) {
        Long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId();
        SysRole info = roleMapper.checkRoleNameUnique(role);
        /*该角色信息不为空，或者，该角色的ID与传进来的角色的Id不相等*/
        if(StringUtils.isNotNull(info) && info.getRoleId().longValue() != roleId.longValue()){
            /*不是唯一的*/
            return UserConstants.NOT_UNIQUE;
        }
        /*是唯一的*/
        return UserConstants.UNIQUE;
    }

    /**
     * 判断该角色权限是否唯一
     */
    @Override
    public boolean checkRoleKeyUnique(SysRole role)
    {
        /*根据角色的权限字段进行查找*/
        Long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId();
        SysRole info = roleMapper.checkRoleKeyUnique(role);
        if (StringUtils.isNotNull(info) && info.getRoleId().longValue() != roleId.longValue())
        {
            /*不是唯一的*/
            return UserConstants.NOT_UNIQUE;
        }
        /*是唯一的*/
        return UserConstants.UNIQUE;
    }

    /**
     * 校验角色是否有数据权限
     *
     * 1. 操作者是超级管理员
     * 2. 操作者不是超级管理员，但是在角色表中可以查找到该角色信息
     * @param roleId 角色id
     */
    public void checkRoleDataScope(Long roleId){
        /*先判断登录的用户是不是超级管理员*/
        if (!SysUser.isAdmin(SecurityUtils.getUserId()))
        {
            SysRole role = new SysRole();
            role.setRoleId(roleId);
            /*不是就进行查询*/
            List<SysRole> roles = SpringUtils.getAopProxy(this).selectRoleList(role);
            /*没查找到抛出异常不存在*/
            if (StringUtils.isNull(roles))
            {
                throw new ServiceException("没有权限访问角色数据！");
            }
        }
    }

    /**
     * 通过ID来进行查询角色信息
     * @param roleId
     * @return
     */
    public SysRole selectRoleById(Long roleId){
        SysRole sysRole = roleMapper.selectRoleById(roleId);
        List<SysRoleMenu> list = roleMenuMapper.selectByRoleId(roleId);
        Long[] menuIds = new Long[list.size()];
        if(list.size() > 0){
            /*将其变成数组*/
            for (int i = 0; i < list.size(); i++) {
                SysRoleMenu sysRoleMenu = list.get(i);
                menuIds[i] = sysRoleMenu.getMenuId();
            }
        }
        sysRole.setMenuIds(menuIds);
        return sysRole;
    }

    /**
     * 新增保存角色信息
     *
     * @param role 角色信息
     * @return 结果
     */
    @Override
    @Transactional
    public boolean insertRole(SysRole role)
    {
        // 新增角色信息
        roleMapper.insertRole(role);
        return insertRoleMenu(role);
    }

    /**
     * 校验角色是否允许操作
     *
     * @param role 角色信息
     */
    public void checkRoleAllowed(SysRole role){
        /*角色的ID值不为空并且不是超级管理员角色*/
        if(StringUtils.isNotNull(role.getRoleId()) && role.isAdmin()){
            throw new ServiceException("不允许操作超级管理员角色");
        }
    }


    /**
     * 修改角色信息
     * @param role
     * @return
     */
    @Override
    @Transactional/*开启事务锁*/
    public boolean updateRole(SysRole role){
        /*修改角色信息表*/
        roleMapper.updateById(role);
        /*根据角色ID删除角色菜单表中的数据*/
        roleMenuMapper.deleteRoleMenuByRoleId(role.getRoleId());
        /*在角色菜单表中进行从新插入*/
        return insertRoleMenu(role);
    }

    /**
     * 修改角色状态
     * @param role
     */
    @Override
    public boolean updateRoleStatus(SysRole role){
        return roleMapper.updateRole(role);
    }


    /**
     * 批量删除角色信息
     * @param roleIds
     * @return
     */
    @Override
    @Transactional
    public int deleteRoleByIds(Long[] roleIds){
        for (Long roleId : roleIds)
        {
            SysRole sysRole = new SysRole();
            sysRole.setRoleId(roleId);
            checkRoleAllowed(sysRole);
            checkRoleDataScope(roleId);
            SysRole role = selectRoleById(roleId);
            if (userRoleMapper.countUserRoleByRoleId(roleId) > 0)
            {
                throw new ServiceException(String.format("%1$s已分配,不能删除", role.getRoleName()));
            }
        }
        // 删除角色与菜单关联
        roleMenuMapper.deleteRoleMenuByRoleIds(roleIds);
        // 删除角色与部门关联
        roleDeptMapper.deleteRoleDeptByRoleIds(roleIds);
        return roleMapper.deleteRoleByIds(roleIds);

        /*判断这些ID都存在，并且都有数据全是安*//*
        List<Long> allowRoleIds  = new ArrayList<Long>();
        List<String> list = new ArrayList<>();
        for (Long roleId : roleIds) {
            SysRole sysRole = new SysRole();
            sysRole.setRoleId(roleId);
            checkRoleAllowed(sysRole);
            checkRoleDataScope(roleId);
            *//*获取该角色信息*//*
            SysRole roleInfo = selectRoleById(roleId);
            //统计用户角色表，该角色有多少个用户正在使用
            if(userRoleMapper.countUserRoleByRoleId(roleId) > 0){
                *//*不能被删除*//*
                list.add(roleInfo.getRoleName());
                //throw new ServiceException(String.format("%1$s已分配,不能删除", roleInfo.getRoleName()));
            }else {
                *//*可以被删除*//*
                allowRoleIds.add(roleId);
            }
        }
        Long[] allowIds = allowRoleIds.toArray(new Long[0]);
        if(allowIds.length > 0) {
            // 删除角色与菜单关联
            roleMenuMapper.deleteRoleMenuByRoleIds(allowIds);
            // 删除角色与部门关联
            roleDeptMapper.deleteRoleDeptByRoleIds(allowIds);
            int rows = roleMapper.deleteRoleByIds(allowIds);
        }
        if(allowIds.length == 0){
            return AjaxResult.error("编号为" + Arrays.toString(allowIds.) + "角色已经分配给用户");
        }
        if(list.size() > 0){
            String string = list.toString();
            return AjaxResult.warn("有" + string + "未删除成功，角色" +
                    "已经分配给用户");
        }
        return AjaxResult.success("删除成功！");*/
     }


    /**
     * 将一个角色分配给多个用户
     * @param roleId 角色ID
     * @param userIds 多个用户ID
     * @return
     */
    @Override
    public boolean insertAuthUsers(Long roleId, Long[] userIds) {
        /*直接更新用户角色表即可*/

        /*将这些角色ID封装成用户角色集合*/
        List<SysUserRole> list = new ArrayList<SysUserRole>();

        for (Long userId : userIds) {
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setUserId(userId);
            sysUserRole.setRoleId(roleId);
            list.add(sysUserRole);
        }
        /*将这些集合装入数据库中*/
        return userRoleService.saveBatch(list);
    }

    /**
     * 批量取消授权用户
     * @param roleId 要取消的角色ID
     * @param userIds 需要取消的用户信息
     * @return
     */
    @Override
    public boolean deleteAuthUsers(Long roleId, Long[] userIds) {

        return userRoleMapper.deleteUserRoleInfos(roleId, userIds);
    }

    /**
     * 取消授权用户
     * @param userRole 用户ID，角色ID
     * @return
     */
    @Override
    public boolean deleteAuthUser(SysUserRole userRole) {
        return userRoleMapper.deleteUserRoleInfo(userRole);
    }


    /**
     * 新增角色菜单信息
     *
     * @param role 角色对象
     */
    public boolean insertRoleMenu(SysRole role){

        /*装角色菜单信息*/
        int rows = 1;
        List<SysRoleMenu> list = new ArrayList<SysRoleMenu>();
        for (Long menuId : role.getMenuIds()) {
            SysRoleMenu sysRoleMenu = new SysRoleMenu();
            sysRoleMenu.setMenuId(menuId);
            sysRoleMenu.setRoleId(role.getRoleId());
            list.add(sysRoleMenu);
        }
        if(list.size() > 0){
            //将数据装入
            rows = roleMenuMapper.batchRoleMenu(list);
        }
        return rows > 0;
    }





}




